<template>
  <div>
    <input type="file" multiple @change="handleFileSelect" />
    <button @click="startAllUploads">开始所有上传</button>
    <div v-for="(fileInfo, index) in selectedFiles" :key="index">
      <p>{{ fileInfo.file.name }}</p>
      <progress :value="fileInfo.progress" max="100"></progress>
      <p>{{ fileInfo.progress }}%</p>
      <button
        @click="pauseResumeUpload(fileInfo)"
        :disabled="!fileInfo.flowFile || fileInfo.progress >= 100"
      >
        {{ fileInfo.isPaused ? '继续上传' : '暂停上传' }}
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import Flow, { type FlowFile } from '@flowjs/flow.js'
  import { calculateFileMd5 } from '@/hooks/calculateFileMd5'

  // 定义文件信息的类型
  interface FileInfo {
    file: File
    progress: number
    md5: string
    flowFile: FlowFile | null
    isPaused: boolean // 新增字段用于记录文件是否被暂停
  }

  // 分片大小
  const CHUNK_SIZE = 5 * 1024 * 1024

  // 存储选中的文件信息
  const selectedFiles = ref<FileInfo[]>([])

  // 创建 Flow.js 实例
  const createFlowInstance = (md5: string): Flow => {
    return new Flow({
      target: '/api/flowjs/chunk', // 上传地址
      singleFile: false, // 是否单文件上传
      chunkSize: CHUNK_SIZE, // 数据块大小
      forceChunkSize: false, // 强制每个数据块大小一致
      simultaneousUploads: 3, // 同时上传的数量
      query: {}, // 额外参数
      headers: {}, // 额外消息头
      withCredentials: false, // 是否携带cookie。标准 CORS 请求默认不发送或设置任何 cookie
      allowDuplicateUploads: false, // 是否允许重新上传相同的文件
      testChunks: true, // 对服务器上的每个块执行 GET 请求以检查其是否存在
      maxChunkRetries: 3, // 最大重试次数
      generateUniqueIdentifier: () => md5
    })
  }

  // 处理文件选择事件
  const handleFileSelect = async (event: Event) => {
    const input = event.target as HTMLInputElement
    if (input.files) {
      for (let i = 0; i < input.files.length; i++) {
        const file = input.files[i]
        const md5 = await calculateFileMd5(file, CHUNK_SIZE)

        const fileInfo: FileInfo = {
          file,
          progress: 0,
          md5,
          flowFile: null,
          isPaused: false // 初始化为未暂停
        }

        selectedFiles.value.push(fileInfo)
      }
    }
  }

  // 开始所有文件的上传
  const startAllUploads = () => {
    selectedFiles.value.forEach((fileInfo) => {
      const flow = createFlowInstance(fileInfo.md5)

      // 监听文件开始上传事件
      flow.on('fileAdded', (flowFile: FlowFile) => {
        console.log(`文件 ${flowFile.name} 开始上传`)
        fileInfo.flowFile = flowFile
      })

      // 监听文件进度事件
      flow.on('fileProgress', (flowFile: FlowFile) => {
        const targetFileInfo = selectedFiles.value.find(
          (item) => item.md5 === flowFile.uniqueIdentifier
        )
        if (targetFileInfo) {
          const progress = Math.round(flowFile.progress() * 100)
          if (progress > targetFileInfo.progress) {
            targetFileInfo.progress = progress
            console.log(`Progress updated for ${flowFile.name}: ${progress}%`)
          }
        }
      })

      // 监听文件上传成功事件
      flow.on('fileSuccess', (flowFile: FlowFile) => {
        const targetFileInfo = selectedFiles.value.find(
          (item) => item.md5 === flowFile.uniqueIdentifier
        )
        if (targetFileInfo) {
          targetFileInfo.progress = 100
          console.log(`${targetFileInfo.file.name} 上传成功`)
        }
      })

      // 监听文件上传错误事件
      flow.on('fileError', (flowFile: FlowFile, message: string) => {
        const targetFileInfo = selectedFiles.value.find(
          (item) => item.md5 === flowFile.uniqueIdentifier
        )
        if (targetFileInfo) {
          console.error(`${targetFileInfo.file.name} 上传失败: ${message}`)
        }
      })

      // 手动添加文件并启动上传
      flow.addFile(fileInfo.file)
      flow.upload()
    })
  }

  // 暂停或恢复上传
  const pauseResumeUpload = (fileInfo: FileInfo) => {
    if (!fileInfo.flowFile) return

    if (fileInfo.isPaused) {
      fileInfo.flowFile.resume()
    } else {
      fileInfo.flowFile.pause()
    }

    fileInfo.isPaused = !fileInfo.isPaused
  }
</script>

<style scoped></style>
